/* ********************************************************************************
 *		Copyright:	(C) 2025 ZYT
 *					All rights reserved.
 *
 *		 Filename:	main.c
 *	  Description:	This file
 *
 *		  Version:	1.0.0(27/03/25)
 *		   Author:	Zhang yuting <zhangyuting@163.com>
 *		ChangeLog:	1, Release initial version on "27/03/25 16:18:04"
 *
 *********************************************************************************/
#include <signal.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <libgen.h>
#include <string.h>

#include "sqlite.h"
#include "socket.h"
#include "client_func.h"
#include "ds18b20.h"
#include "logger.h"
#include "pack.h"
void program_stop(int sigsum);
void handle_pipe(int sig);

int g_prog_stop = 0;


#define PIDFILE   "/tmp/.socketdi_h_c.pid"

int main(int argc, char **argv)
{
	char           *progname=NULL;
	char		   *serv_ip = NULL;
	int				serv_port;
	int				interval_time = 30;
	char		   *sn = NULL;
	int				daemon_flag = 0;
	int				opt;

	float			temper;
	long			now_time = 0;
	long			pre_time = 0;
	char			buffer[128];
	char		   *format_time = NULL;
	char			*logfile = "running.log";
	char			loglevel = LOG_LEVEL_INFO;

	int				rv = -1;
	int				sockfd = -1;
	sqlite3		   *sql_db;
	int				sample_flag = 0;
	int				len = 0;
	packet_t		pack;
	pack_proc_t     pack_proc = pack_data;

	struct option	opt_long[] =
	{
		{"serv_ip", required_argument, NULL, 'i'},
		{"serv_port", required_argument, NULL, 'p'},
		{"interval_time", required_argument, NULL, 't'},
		{"sn", required_argument, NULL, 's'},
		{"background", no_argument, NULL, 'b'},
		{"debug", no_argument, NULL, 'd'},
		{"help", no_argument, NULL, 'h'},
		{"Pack", required_argument, NULL, 'P'},
		{"Stop", no_argument, NULL, 'S'},
		{NULL, 0, NULL, 0}
	};

	progname = (char *)basename(argv[0]);

	while( (opt = getopt_long(argc, argv, "i:p:t:s:bdh:P:S", opt_long, NULL)) != -1 )
	{
		switch(opt)
		{
			case 'i':
				serv_ip = optarg;
				break;
			case 'p':
				serv_port = atoi(optarg);
				break;
			case 't':
				interval_time = atoi(optarg);
				break;
			case 's':
				sn = optarg;
				break;
			case 'b':
				daemon_flag = 1;
				break;
			case 'd':
				daemon_flag = 0;
				logfile = "stderr";
				loglevel = LOG_LEVEL_DEBUG;
				break;
			case 'h':
				print_usage(argv[0]);
				return 0;
			case 'P':
				if ( strcmp(optarg, "json") == 0 )
				{
					pack_proc = pack_data_json;
				}
				else if ( strcmp(optarg, "tlv") == 0 )
				{
					pack_proc = pack_data_tlv;
				}
				else
				{
					print_usage(argv[0]);
				}
				break;
			case 'S':
				stop_background_running(PIDFILE);
				return 0;
			default :
				print_usage(argv[0]);
				return 0;
		}
	}

	while( !serv_ip || !serv_port || !interval_time || !sn )
	{
		print_usage(argv[0]);
		return -1;
	}
	/* 初始化Logger  */
	if( log_open(logfile, loglevel, 10, 0) < 0 )
	{
		fprintf(stderr, "initial logger system failure\n");
		exit(1);
	}

	signal(SIGINT, program_stop);
	signal(SIGTERM, program_stop);

	if ( !set_background_running(daemon_flag, PIDFILE) )
	{
		log_close();
		unlink(PIDFILE);
	}

	/* 初始化数据库 */
	if(sql_init(&sql_db, sn) < 0 )
	{
		log_error("sql_init failure.\n");
	}
	log_info("sql_init successfully.\n");


	while( !g_prog_stop )
	{
		sample_flag = 0;
		time(&now_time);

		if( difftime(now_time, pre_time) >= interval_time )
		{
			/* 获取温度、时间 */
			memset(&pack, 0, sizeof(pack));

			strncpy(pack.dev_sn, sn, sizeof(pack.dev_sn));				/*   设备号 */
			get_time(pack.dev_time);									/*   获取当前日期时间 */
			get_temperature(&pack.dev_temp);							/*   采集温度 */ 

			sample_flag = 1;
			pre_time = now_time;//更新时间
		}

		/* 连接维护 */
		if( socket_check(sockfd) < 0 )
		{
			log_error("socket disconnect.\n");

			if( sockfd > 0 )
			{
				close(sockfd);
				log_error("close sockfd.\n");
			}
			/* 重新连接服务器 */
			sockfd = socket_connect(serv_ip, serv_port);
		}
		/* 重连失败，数据存入数据库 */
		if( socket_check(sockfd) < 0 )
		{
			if( sample_flag )
			{
				if( sql_insert(sql_db, sn, &pack) < 0 )
				{
					log_error("reconnect failure and sql_insert failure\n");
					continue;
				}
				log_info("no connect but sql_insert\n");

			}
			continue;
		}

		/*  socket链接成功 */

		if( sample_flag )
		{
			/* 有采样就发送数据 */
			len = pack_proc(&pack, (uint8_t *)buffer, sizeof(buffer));
			if( len < 0 )
			{
				log_error("pack_data failure:%s\n",strerror(errno));
				continue;
			}
			log_info("pack_data successfully\n");

			if( socket_write(sockfd, buffer, len) < 0 )
			{
				log_error("sql write to server failure.\n");

				sql_insert(sql_db, sn, &pack);

				close(sockfd);
				continue;
			}
			log_info("sql write to server successfully.\n");
		}
		/* 检查本地数据库是否有缓存数据,取单条发送 */
		if( sql_query(sql_db, &pack) )
		{
			log_info("sql have data.start send data...\n");

			len = pack_proc(&pack, (uint8_t *)buffer, sizeof(buffer));
			
			if ( len < 0 )
			{
				log_error("pack data failure\n");
				continue;
			}

			if( socket_write(sockfd, buffer, len) < 0 )
			{
				log_error("write local data to server failure: %s.\n", strerror(errno));

				close(sockfd);
				continue;
			}

			sql_delete(sql_db, sn);
			log_info("write local data(%s) to server successfully.\n", buffer);
		}

	}//end of while

	log_info(" Client process exiting...\n");
	close(sockfd);
	sql_close(&sql_db);
	log_close();
	unlink(PIDFILE);

	return 0;
}

void program_stop(int sigsum)
{
	g_prog_stop = 1;
}


